package com.itheima.advice;

import com.alibaba.dubbo.config.annotation.Reference;
import com.itheima.annotaion.SystemControllerLog;
import com.itheima.entity.Result;
import com.itheima.pojo.Journal;
import com.itheima.service.JournalService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Date;

/**
 * @author ldl.plus
 * @date 2020年04月24日  21:17
 */
public class CustomAspect {

    private static final Logger logger = LoggerFactory.getLogger(CustomAspect.class);

    @Reference
    private JournalService journalService;

    @Autowired
    private HttpServletRequest request;

    public Object operationLog(ProceedingJoinPoint pjp) {
//        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        // 获取方法签名
        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        // 获取方法对象
        Method method = methodSignature.getMethod();
        // 获取方法上的日志注解
        SystemControllerLog anno = method.getAnnotation(SystemControllerLog.class);
        Object proceed;
        long start = 0;
        long end = 0;
        // 执行方法
        try {
            start = System.currentTimeMillis();
            proceed = pjp.proceed();
            end = System.currentTimeMillis();
            return proceed;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            end = System.currentTimeMillis();
            if (anno != null) {
                Class<?> returnType = method.getReturnType();
                if (returnType == Result.class) {
                    // 获取注解里面描述的类型 对应 String value() default "";
                    String errorMessage = anno.value();
                    // 返回Result对象
                    return new Result(false, errorMessage);
                }
            }
            return null;
        } finally {
            // 日志对象
            Journal journal = new Journal();
            // 获取操作者
            org.springframework.security.core.userdetails.User user = (org.springframework.security.core.userdetails.User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            String username = null;
            if (user != null) {
                username = user.getUsername();
            }
            journal.setOperator(username);
            // 操作时间
            String curDate = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss").format(new Date());
            journal.setOperatorTime(curDate);
//            journal.setOperatorTime(LocalDateTime.now().toString());
            // 操作者IP
            String ip = null;

            //X-Forwarded-For：Squid 服务代理
            String ipAddresses = request.getHeader("X-Forwarded-For");
            if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
                //Proxy-Client-IP：apache 服务代理
                ipAddresses = request.getHeader("Proxy-Client-IP");
            }
            if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
                //WL-Proxy-Client-IP：weblogic 服务代理
                ipAddresses = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
                //HTTP_CLIENT_IP：有些代理服务器
                ipAddresses = request.getHeader("HTTP_CLIENT_IP");
            }
            if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
                //X-Real-IP：nginx服务代理
                ipAddresses = request.getHeader("X-Real-IP");
            }

            //有些网络通过多层代理，那么获取到的ip就会有多个，一般都是通过逗号（,）分割开来，并且第一个ip为客户端的真实IP
            if (ipAddresses != null && ipAddresses.length() != 0) {
                ip = ipAddresses.split(",")[0];
            }

            //还是不能获取到，最后再通过request.getRemoteAddr();获取
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
                ip = request.getRemoteAddr();
            }
            ip = "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
            journal.setOperatorIp(ip);
            // 地址
            journal.setOperatorUrl(request.getRequestURI());
            // 执行时长
            journal.setImplementTime(end - start + "");
            // 全限定类名
            journal.setClassname(pjp.getTarget().getClass().getName());
            // 方法名
            journal.setMethodName(method.getName());
            journal.setMethodParameter(Arrays.toString(pjp.getArgs()));

            logger.info(journal.toString());
            journalService.addLog(journal);
        }
    }

}
